//
//  SBPageController.m
//  Pods
//
//  Created by 刘 真 on 7/19/16.
//
//

#import "SBPageController.h"

@interface SBPageController () <UIScrollViewDelegate>

@property (nonatomic, strong) UIScrollView *scrollView;

@property (nonatomic, weak) UIViewController *before;

@property (nonatomic, weak) UIViewController *current;

@property (nonatomic, weak) UIViewController *after;

/**
 *  将要显示的控制器
 */
@property (nonatomic, weak) UIViewController *willAppearing;

/**
 *  将要隐藏的控制器
 */
@property (nonatomic, weak) UIViewController *willDisappear;

/**
 *  原始偏移信息
 */
@property (nonatomic) CGPoint originOffset;

/**
 *  标记是否要追踪偏移的变化
 */
@property (nonatomic) BOOL trackingOffset;

/**
 *  用来标记是否需要忽略dragging
 */
@property (nonatomic) BOOL ignoreDragging;

@end

@implementation SBPageController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //构造ScrollView
    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    self.scrollView.showsVerticalScrollIndicator = NO;
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.scrollView.pagingEnabled = YES;
    self.scrollView.delegate = self;
    self.scrollView.scrollsToTop = NO;
    self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:self.scrollView];
    
}

- (void)setViewController:(UIViewController *)viewController {
    
    if (self.before) {
        [self.before removeFromParentViewController];
        self.before = nil;
    }
    
    if (self.after) {
        [self.after removeFromParentViewController];
        self.after = nil;
    }
    
    if (_current != viewController) {
        [_current removeFromParentViewController];
        [_current.view removeFromSuperview];
        _current = viewController;
        
        if (_current) {
            [self addChildViewController:_current];
            [self.current didMoveToParentViewController:self];
        }
    }
    [self updateContentSize];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    NSAssert(self.current, @"未设置currentViewController");
    
    //从数据源获取控制器
    UIViewController *before = [self pageController:self viewControllerBeforeViewController:self.current];
    UIViewController *after = [self pageController:self viewControllerAfterViewController:self.current];
    
    //展示current控制器
    if (self.current) {
        [self.current beginAppearanceTransition:YES animated:NO];
        self.current.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        [self.scrollView addSubview:self.current.view];
        [self.current endAppearanceTransition];
        [self childDidAppear:self.current];
    }
    
    if (before) {
        [before willMoveToParentViewController:self];
        [self addChildViewController:before];
        [before didMoveToParentViewController:self];
        self.before = before;
    }
    
    if (after) {
        [after willMoveToParentViewController:self];
        [self addChildViewController:after];
        [after didMoveToParentViewController:self];
        self.after = after;
    }
    [self updateContentSize];
}

//防止addSubview自动调用will appear, did appear方法
- (BOOL)shouldAutomaticallyForwardAppearanceMethods {
    return NO;
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    [self updateContentSize];
}

- (void)updateContentSize {
    
    //布局子控制器
    CGSize size = self.view.bounds.size;
    size.height -= self.scrollView.contentInset.top - self.scrollView.contentInset.bottom;
    size.width = self.view.bounds.size.width * MIN(self.childViewControllers.count, 3);
    self.scrollView.contentSize = size;
    
    CGRect frame = self.current.view.frame;
    frame.size.height = _scrollView.frame.size.height;
    self.current.view.frame = frame;
}

- (void)willAppearChild:(UIViewController *)childToAppear beforeChild:(UIViewController *)child animated:(BOOL)animated {
    assert(childToAppear != nil);
    childToAppear.view.frame = CGRectOffset(child.view.frame, -CGRectGetWidth(self.view.frame), 0);
    [childToAppear beginAppearanceTransition:YES animated:animated];
    childToAppear.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
    [self.scrollView addSubview:childToAppear.view];
    
    [child beginAppearanceTransition:NO animated:animated];
}

- (void)willAppearChild:(UIViewController *)childToAppear afterChild:(UIViewController *)child animated:(BOOL)animated {
    assert(childToAppear != nil);
    childToAppear.view.frame = CGRectOffset(child.view.frame, CGRectGetWidth(self.view.frame), 0);
    [childToAppear beginAppearanceTransition:YES animated:animated];
    childToAppear.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
    [self.scrollView addSubview:childToAppear.view];
    
    [child beginAppearanceTransition:NO animated:NO];
}

//取消之前的will appear行为
- (void)cancelAppearChild:(UIViewController *)childToAppear disappearChild:(UIViewController *)childToDisappear {
    [childToAppear beginAppearanceTransition:NO animated:NO];
    [childToAppear.view removeFromSuperview];
    [childToAppear endAppearanceTransition];
    
    [childToDisappear beginAppearanceTransition:YES animated:NO];
    [childToDisappear endAppearanceTransition];
}

//结束的时侯，是一致的，所以这里只需要一个函数
- (void)didAppearChild:(UIViewController *)childToAppear disappearChild:(UIViewController *)childToDisappear {
    [childToAppear endAppearanceTransition];
    [childToDisappear endAppearanceTransition];
    [childToDisappear.view removeFromSuperview];
    
    [self childDidAppear:childToAppear];
}

- (void)moveForwardWithChild:(UIViewController *)before {
    
    //如果前面已经为空，这时无法再添加一个空的控制器进来
    if (!self.before) {
        NSLog(@"before为空，无法前移");
        return;
    }
    
    //如果要在最前面加入一个控制器，则将最后面的控制器，然后顺移，原current会移到最后，原before会移到current, 新加的before会成为新的before
    if (self.after) {
        NSLog(@"remove child %@", self.after);
        [self.after willMoveToParentViewController:self];
        [self.after removeFromParentViewController];
        if (self.after.isViewLoaded) {
            [self.after.view removeFromSuperview];
        }
        [self.after didMoveToParentViewController:self];
    }
    
    //依次顺移
    self.after = self.current;
    self.current = self.before;
    self.before = before;
    
    if (before) {
        [before willMoveToParentViewController:self];
        [self addChildViewController:before];
        [before didMoveToParentViewController:self];
    }
}

- (void)moveBackwardWithChild:(UIViewController *)after {
    
    //如果前面已经为空，这时无法再添加一个空的控制器进来
    if (!self.after) {
        NSLog(@"after为空，无法后移");
        return;
    }
    
    //如果要在最前面加入一个控制器，则将最后面的控制器，然后顺移，原current会移到最后，原before会移到current, 新加的before会成为新的before
    if (self.before) {
        NSLog(@"remove child %@", self.before);
        [self.before willMoveToParentViewController:self];
        [self.before removeFromParentViewController];
        if (self.before.isViewLoaded) {
            [self.before.view removeFromSuperview];
        }
        [self.before didMoveToParentViewController:self];
    }
    
    //依次顺移
    self.before = self.current;
    self.current = self.after;
    self.after = after;
    
    if (after) {
        [after willMoveToParentViewController:self];
        [self addChildViewController:after];
        [after didMoveToParentViewController:self];
    }
}

#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    self.originOffset = self.scrollView.contentOffset;
    self.trackingOffset = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    //将滚动信息回调给外面
    if (self.trackingOffset && !self.ignoreDragging) {
        [self childDidScrollOffset:(self.scrollView.contentOffset.x - self.originOffset.x)/CGRectGetWidth(self.view.bounds)];
    }

    //只有用户滚动，才触发下面的操作
    if (!scrollView.dragging && !self.ignoreDragging) {
        return;
    }
    
    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat originX = self.current.view.frame.origin.x;
    
    if (offsetX > originX) {
        
        if (self.after && self.willAppearing != self.after) {
            
            self.willDisappear = self.current;
            self.willAppearing = self.after;

            [self willAppearChild:self.willAppearing afterChild:self.willDisappear animated:YES];
        }
    }
    else if (offsetX < originX ) {
        
        if (self.before && self.willAppearing != self.before) {
            
            self.willDisappear = self.current;
            self.willAppearing = self.before;

            [self willAppearChild:self.willAppearing beforeChild:self.willDisappear animated:YES];
        }
    }
    else {
        
    }
}

//如果是通过调用api来滚动的话，那么将不会触发scrollViewDidEndDecelerating方法，所以这里手工调一次
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    [self scrollViewDidEndDecelerating:scrollView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    
    if (!self.ignoreDragging) {
        [self childDidScrollOffset:(self.scrollView.contentOffset.x - self.originOffset.x)/CGRectGetWidth(self.view.bounds)];
    }
    
    self.trackingOffset = NO;
    self.ignoreDragging = NO;
    self.originOffset = CGPointZero;
    
    if (self.willAppearing) {
        
        CGFloat offsetX = scrollView.contentOffset.x;
        CGFloat originX = self.current.view.frame.origin.x;
        
        if (offsetX != originX) {
            [self didAppearChild:self.willAppearing disappearChild:self.willDisappear];
            
            //这里要做一个调整，是originX和OffsetX相等，这样才能保证无限的划动下去
            if (self.willAppearing == self.before) {
                UIViewController *before = [self pageController:self viewControllerBeforeViewController:self.willAppearing];
                [self moveForwardWithChild:before];
            }
            else if (self.willAppearing == self.after) {
                UIViewController *after = [self pageController:self viewControllerAfterViewController:self.willAppearing];
                [self moveBackwardWithChild:after];
            }
            
            [self updateContentSize];
            
            //修正偏移
            CGFloat dx = 0;
            
            CGFloat w = CGRectGetWidth(self.view.bounds);
            CGFloat h = CGRectGetHeight(self.view.bounds) - self.scrollView.contentInset.top - self.scrollView.contentInset.bottom;

            if (self.before) {
                dx = CGRectGetWidth(self.view.bounds);
                self.before.view.frame = CGRectMake(0, 0, w, h);
            }
            
            self.current.view.frame = CGRectMake(0, 0, w, h);
            self.current.view.frame = CGRectOffset(self.current.view.frame, dx, 0);
            self.scrollView.contentOffset = CGPointMake(dx, self.scrollView.contentOffset.y);
        }
        else {
            [self cancelAppearChild:self.willAppearing disappearChild:self.willDisappear];
        }
        
        self.willAppearing = nil;
        self.willDisappear = nil;
    }
}

- (void)childDidAppear:(UIViewController *)child {
    
}

- (void)childDidScrollOffset:(CGFloat)offset {
    
}

- (void)moveNext {
    self.originOffset = self.scrollView.contentOffset;
    self.trackingOffset = YES;
    self.ignoreDragging = YES;

    CGPoint offset = self.scrollView.contentOffset;
    offset.x += CGRectGetWidth(self.view.bounds);
    [self.scrollView setContentOffset:offset animated:YES];
}

- (void)moveBefore {
    self.originOffset = self.scrollView.contentOffset;
    self.trackingOffset = YES;
    self.ignoreDragging = YES;
    
    CGPoint offset = self.scrollView.contentOffset;
    offset.x -= CGRectGetWidth(self.view.bounds);
    [self.scrollView setContentOffset:offset animated:YES];
}

#pragma mark - overwrite methods
- (nullable UIViewController *)pageController:(SBPageController *)pageController viewControllerBeforeViewController:(UIViewController *)viewController {
    return nil;
}

- (nullable UIViewController *)pageController:(SBPageController *)pageController viewControllerAfterViewController:(UIViewController *)viewController {
    return nil;
}

- (NSInteger)presentationCountForPageViewController:(SBPageController *)pageViewController {
    return 0;
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
    return 0;
}

@end
